from __future__ import absolute_import
from celery import shared_task
from mapp.core.parsers import BasicParser, ValuesParser
from mapp.utils.common import parse_mutations, analyse_mutations
from mapp.core.analyzers import Analyzer
from mapp.core.exceptions import MappError
from celery.utils.log import get_task_logger
from mappapp.settings import *  # @UnusedWildImport
logger = get_task_logger(__name__)



@shared_task
def run_mapp(seqid, sequence, mutations, mapp_settings):
    ''' Runs mapp analysis with mapp_settings '''
    logger.info("Mapp task for id=%s" % seqid)
    create_sequence_file(seqid, sequence)
    create_mutations_file(seqid, mutations)
    mapp = Analyzer(ValuesParser(mapp_settings))
    try:
        mapp.exec_mapp()
    except MappError as e:
        logger.error("MappError for id=%s\n%s\n%s\n" % (seqid, e.header, e.description))
        return False


def create_settings(seqid, clusters=50, initseqs=25000, msa='mafft',
                    tree='fasttree'):
    ''' Creates mapp_settings for `run_mapp` method '''
    settings = dict()
    settings[BasicParser.SEQUENCE_FILE] = MAPP_SEQ_FILE.format(id=seqid)
    settings[BasicParser.BLAST_OUTFILE] = MAPP_BLAST_FILE.format(id=seqid)
    settings[BasicParser.BLASTSTAT_OUTFILE] = MAPP_STAT_FILE.format(id=seqid)
    settings[BasicParser.MAPP_OUTFILE] = MAPP_FILE.format(id=seqid)
    settings[BasicParser.MSA_OUTFILE] = MAPP_MSA_FILE.format(id=seqid)
    settings[BasicParser.TREE_OUTFILE] = MAPP_TREE_FILE.format(id=seqid)
    
    #refs variable is passed to the MAPP_PROGRAMS string.format(**refs)
    # so user can use reference in MAPP_PROGRAMS string to the file names
    # in settings. E. g. MAPP_PROGRAMS['BLAST']="blastp -i {sequence} -o {blastout}" and
    #before run it will call like MAPP_PROGRAMS['BLAST'].format(**refs)
    refs = {'clusters': clusters,
            'initseqs': initseqs,
            BasicParser.SEQUENCE_FILE: settings[BasicParser.SEQUENCE_FILE],
            BasicParser.BLAST_OUTFILE: settings[BasicParser.BLAST_OUTFILE],
            BasicParser.BLASTSTAT_OUTFILE: settings[BasicParser.BLASTSTAT_OUTFILE],
            BasicParser.MAPP_OUTFILE: settings[BasicParser.MAPP_OUTFILE],
            BasicParser.MSA_OUTFILE: settings[BasicParser.MSA_OUTFILE],
            BasicParser.TREE_OUTFILE: settings[BasicParser.TREE_OUTFILE]}
    
    settings[BasicParser.BLAST_PROGRAM] = MAPP_PROGRAMS['BLAST'].format(**refs)
    settings[BasicParser.TREE_PROGRAM] = MAPP_PROGRAMS['TREE'].format(**refs)
    if msa == 'mafft':
        settings[BasicParser.MSA_PROGRAM] = MAPP_MAFFT.format(**refs)
    elif msa == 'clustalo':
        settings[BasicParser.MSA_PROGRAM] = MAPP_CLUSTALO.format(**refs)
    else:
        raise AttributeError('msa attribute has wrong value: %s' % msa)
    if tree == 'fasttree':
        settings[BasicParser.TREE_PROGRAM] = MAPP_FASTTREE.format(**refs)
    elif tree == 'raxml':
        settings[BasicParser.TREE_PROGRAM] = MAPP_RAXML.format(**refs)
    else:
        raise AttributeError('tree attribute has wrong value: %s' % tree)
    settings[BasicParser.MAPP_PROGRAM] = MAPP_PROGRAMS['MAPP'].format(**refs)
    settings[BasicParser.BEFOREMSA_PROGRAM] = MAPP_PROGRAMS['BEFOREMSA'].format(**refs)
    settings[BasicParser.BEFORETREE_PROGRAM] = MAPP_PROGRAMS['BEFORETREE'].format(**refs)
    settings[BasicParser.BEFOREMAPP_PROGRAM] = MAPP_PROGRAMS['BEFOREMAPP'].format(**refs)
    return settings



def write_csv_results(query_id, mutations, writable):
    import csv
    results = get_results(query_id, mutations)
    writer = csv.writer(writable)
    writer.writerow(['mutation', 'prediction', 'pvalue', 'alignment'])
    for mut in results: 
        writer.writerow([mut['mutation'], mut['prediction'],
                         mut['pvalue'], mut['alignment']])
    return writable

    
def get_results(query_id, mutations): 
    with open(MAPP_MSA_FILE.format(id=query_id)) as msa:
            with open(MAPP_FILE.format(id=query_id)) as mapp:
                results = analyse_mutations(query_id,
                                            mutations,
                                            msa.read(),
                                            mapp.read(),
                                            MAPP_PVALUE)
    return results


def create_sequence_file(seqid, sequence):
    with open(MAPP_SEQ_FILE.format(id=seqid), 'w') as f:
        f.write(">%s\n%s\n" % (seqid, sequence))
        




def create_mutations_file(seqid, mutations): 
    with open(MAPP_MUTS_FILE.format(id=seqid), 'w') as f:
        mutlist = parse_mutations(mutations)
        for mutation in mutlist:
            f.write(''.join(map(str,mutation)) + '\n')
        
    